﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using ReagentStore.BLL;
using ReagentStore.ERM;
using ReagentStore.UTL;
using Timer = System.Timers.Timer;

namespace ReagentStore
{
	public partial class RecordDialog : Form
	{
		private readonly Dictionary<RadioButton, string> _dictType = new Dictionary<RadioButton, string>();
		private readonly PassParamsHandler<Record> _feedbackHandler;
		private readonly DialogParam<Record> _param;

		private readonly BackgroundWorker _worker = new BackgroundWorker
		                                            	{WorkerReportsProgress = true, WorkerSupportsCancellation = true};

		private string _currentType;
		private FormValidator _formValidator;
		private IList<Product> _products;

		public RecordDialog(DialogParam<Record> param, PassParamsHandler<Record> handler)
		{
			InitializeComponent();

			StartTimer();
			DisableControls();

			_param = param;
			_feedbackHandler = handler;

			InitializeDictionary();
			InitializeComboReagent();
			InitializeValidator();
			InitializeControlsByParam();
		}

		private void InitializeDictionary()
		{
			_dictType.Add(radioIncoming, "发票号");
			_dictType.Add(radioOutgoing, "领用人");
			_dictType.Add(radioWear, "损耗原因");
		}

		private void InitializeComboReagent()
		{
			IList<Reagent> reagents = new ReagentBLL().DALAccessor.GetEntities();
			comboReagent.DataSource = reagents;
			comboReagent.DisplayMember = "Name";
			comboReagent.ValueMember = "ReagentID";
			comboReagent.SelectedIndex = -1;
		}

		private void comboReagent_SelectedIndexChanged(object sender, EventArgs e)
		{
			DisableControls();

			if (string.IsNullOrEmpty(comboReagent.ValueMember))
				return;

			if (comboReagent.SelectedIndex < 0)
				return;

			BuildListViewProduct();
			BuildLabelDescription();
		}

		private void listviewProduct_SelectedIndexChanged(object sender, EventArgs e)
		{
			EnableControls();
			BuildLabelDescription();
		}

		private void BuildListViewProduct()
		{
			listviewProduct.Items.Clear();

			var reagentId = (int) comboReagent.SelectedValue;
			_products = new ProductBLL().DALAccessor.GetEntitiesByReagentId(reagentId);

			foreach (ListViewItem item in from product in _products
			                              let subitems = new[]
			                                             	{
			                                             		product.Manufacturer,
			                                             		product.Batch,
			                                             		product.ExpirationDate.ToShortDateString()
			                                             	}
			                              select new ListViewItem(subitems) {Tag = product})
				listviewProduct.Items.Add(item);
		}

		private void BuildLabelDescription()
		{
			if (comboReagent.SelectedIndex < 0)
			{
				labelDescription.Text = "请选择试剂";
				return;
			}

			if (listviewProduct.SelectedItems.Count <= 0)
			{
				labelDescription.Text = "请从列表中选择产品";
				return;
			}

			Reagent reagent = new ReagentBLL().DALAccessor.GetEntityById((int) comboReagent.SelectedValue);
			var product = listviewProduct.SelectedItems[0].Tag as Product;

			if ((reagent == null)
			    || (product == null))
				return;

			const string format = "{1}: 库存{2}{0}\r\n\r\n产品: 库存{3}{0}";
			labelDescription.Text = string.Format(format,
			                                      reagent.Unit,
			                                      reagent.Name,
			                                      reagent.Quantity(),
			                                      product.Quantity()
				);
		}

		private void SetMaxCount()
		{
			if (string.IsNullOrEmpty(_currentType))
				return;

			if (_currentType.Equals("发票号"))
				numCount.Maximum = decimal.MaxValue;
			else
			{
				if (listviewProduct.SelectedItems.Count <= 0)
					return;

				var product = listviewProduct.SelectedItems[0].Tag as Product;
				if (product == null)
					return;
				else
					numCount.Maximum = product.Quantity();
			}
		}

		private void radio_CheckedChanged(object sender, EventArgs e)
		{
			foreach (RadioButton radioButton in _dictType.Keys.Where(radioButton => radioButton.Checked))
				_currentType = _dictType[radioButton];

			labelMemo.Text = _currentType;
			SetMaxCount();
		}

		private void DisableControls()
		{
			labelMemo.Visible = false;
			textMemo.Visible = false;
			numCount.Enabled = false;
		}

		private void EnableControls()
		{
			labelMemo.Visible = true;
			textMemo.Visible = true;
			numCount.Enabled = true;
			SetMaxCount();
		}

		private void InitializeValidator()
		{
			_formValidator = new FormValidator(errorProvider);

			_formValidator.Add(new RequiredValidator(comboReagent, "请选择试剂"));
			_formValidator.Add(new RequiredValidator(listviewProduct, "请选择产品"));
			_formValidator.Add(new RequiredValidator(textMemo, "请输入说明"));
		}

		private void InitializeControlsByParam()
		{
			Record record = _param.Parameter;
			if (record == null)
				return;

			if (record.ProductID > 0)
			{
				Product product = new ProductBLL().DALAccessor.GetEntityById(record.ProductID);
				comboReagent.SelectedValue = product.ReagentID;

				foreach (ListViewItem item in listviewProduct.Items)
				{
					var p = item.Tag as Product;
					if (p == null)
						break;

					if (p.ProductID.Equals(product.ProductID))
					{
						item.Selected = true;
						break;
					}
				}
			}

			switch (record.GetType().Name)
			{
				case "IncomingRecord":
					radioIncoming.Checked = true;
					break;

				case "OutgoingRecord":
					radioOutgoing.Checked = true;
					break;

				case "WearRecord":
					radioWear.Checked = true;
					break;
			}
		}

		private void Feedback()
		{
			Record record = null;
			DateTime now = DateTime.Now;
			var count = (int) numCount.Value;
			int productId = ((Product) listviewProduct.SelectedItems[0].Tag).ProductID;
			string text = textMemo.Text;

			switch (_currentType)
			{
				case "发票号":
					record = IncomingRecord.CreateIncomingRecord(0, now, count, productId, text);
					break;

				case "领用人":
					record = OutgoingRecord.CreateOutgoingRecord(0, now, count, productId, text);
					break;

				case "损耗原因":
					record = WearRecord.CreateWearRecord(0, now, count, productId, text);
					break;
			}

			PassParamsHandler<Record> handler = _feedbackHandler;
			if (handler != null)
				handler(new DialogParam<Record>(record));
		}

		private void RecordDialog_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (DialogResult != DialogResult.OK)
				return;

			errorProvider.SetError(groupType, string.Empty);
			if (string.IsNullOrEmpty(_currentType))
			{
				errorProvider.SetError(groupType, "请选择记录类型");
				e.Cancel = true;
				return;
			}

			if (!_formValidator.IsValid())
			{
				e.Cancel = true;
				return;
			}

			Feedback();
			_worker.CancelAsync();
		}


		private void StartTimer()
		{
			const string format = "yyyy年MM月dd日 tthh:mm:ss";
			labelTime.Text = DateTime.Now.ToString(format);

			_worker.DoWork += (s, e) =>
			                  	{
			                  		var timer = new Timer(1000) {AutoReset = true};
			                  		timer.Elapsed += (ts, te) => _worker.ReportProgress(0);

			                  		timer.Start();

			                  		while (true)
			                  		{
			                  			if (_worker.CancellationPending)
			                  			{
			                  				e.Cancel = true;
			                  				timer.Stop();
			                  				timer.Close();
			                  				return;
			                  			}
			                  		}
			                  	};

			_worker.ProgressChanged += (s, e) => { labelTime.Text = DateTime.Now.ToString(format); };

			_worker.RunWorkerAsync();
		}
	}
}